package com.wtwd.device.filter;

import com.wtwd.device.common.RespCode;
import com.wtwd.device.service.GatewayRedisService;
import com.wtwd.device.util.JWTUtil;
import com.wtwd.device.utils.FilterUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author zdl
 * @Description
 * @create 2021-08-18 17:32
 */
@Component
public class TokenAccessGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenAccessGatewayFilterFactory.Config> {

    private static final Logger log = LoggerFactory.getLogger(TokenAccessGatewayFilterFactory.class);
    @Resource
    private GatewayRedisService redisService;

    /**
     * 1.效验token合法性
     *
     * @param config
     * @return
     */
    @Override
    public GatewayFilter apply(Config config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getPath().value();
            //不需要认证的资源
            if (isAnonResources(path, config.anonResources) || AccessFilter.IS_ACCESSED.equals(exchange.getResponse().getHeaders().getFirst(AccessFilter.IS_ACCESS_FIELD))) {
                return chain.filter(exchange);
            }
            ServerHttpResponse response = exchange.getResponse();
            String token = request.getHeaders().getFirst(config.accessField);
            Long userId = JWTUtil.getUserId(token);
            if (userId == null) {
                return FilterUtil.response(response, RespCode.TOKEN_UNAUTHORIZED);
            }
            String value = redisService.getValue(userId);
            if (value == null) {
                return FilterUtil.response(response, RespCode.TOKEN_UNAUTHORIZED);
            }
            if (!token.equals(value)) {
                return FilterUtil.response(response, RespCode.TOKEN_CONFLICT);
            }
            return chain.filter(exchange);
        };
    }

    boolean isAnonResources(String path, List<String> resources) {
        if (resources == null) return false;
        for (String s : resources) {
            if (path.contains(s)) {
                return true;
            }
        }
        return false;
    }

    public TokenAccessGatewayFilterFactory() {
        super(Config.class);
        log.info("Loaded GatewayFilterFactory [TokenAccessFilter....]");
    }

    public static class Config {
        private String accessField;
        private List<String> anonResources;

        public String getAccessField() {
            return accessField;
        }

        public void setAccessField(String accessField) {
            this.accessField = accessField;
        }

        public List<String> getAnonResources() {
            return anonResources;
        }

        public void setAnonResources(List<String> anonResources) {
            this.anonResources = anonResources;
        }
    }

}
